package com.jackrain.nea.core.service;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSONObject;
import com.jackrain.nea.config.Resources;
import com.jackrain.nea.core.api.CloneTableCmd;
import com.jackrain.nea.core.db.Tools;
import com.jackrain.nea.core.mapper.*;
import com.jackrain.nea.core.schema.Column;
import com.jackrain.nea.core.schema.Table;
import com.jackrain.nea.core.schema.TableManager;
import com.jackrain.nea.exception.NDSException;
import com.jackrain.nea.sys.CommandAdapter;
import com.jackrain.nea.util.ValueHolder;
import com.jackrain.nea.web.face.User;
import com.jackrain.nea.web.query.DefaultWebEvent;
import com.jackrain.nea.web.query.QuerySession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;

@Slf4j
@Component
@Service(protocol = "dubbo", validation = "true", version = "1.0", group = "ad")
public class CloneTableCmdImpl extends CommandAdapter implements CloneTableCmd {

    @Autowired
    private MapperShortcut mapperShortcut;
    @Autowired
    private DirectoryMapper directoryMapper;
    @Autowired
    private AdTableMapper adTableMapper;
    @Autowired
    private AdColumnMapper adColumnMapper;
    @Autowired
    private AdRefbyTableMapper adRefbyTableMapper;
    @Autowired
    private AdTableSqlMapper adTableSqlMapper;


    public void copycolumn(long destabid, String destable, Column srccol, int keeporderno, HashMap<Long, Long> idMapper) throws Exception {

        int orderno = srccol.getDisplayOrder();

        if (keeporderno == 0) {
            orderno = adColumnMapper.getMaxOrderNo(srccol.getTable().getId());
        }


        long newcolid = idMapper.get((long)srccol.getId());
        JSONObject model = adColumnMapper.selectFullByid(srccol.getId());
        model = keyToUpper(model);
        model.put("ID", newcolid);
        model.put("NAME", destable.toUpperCase() + '.' + srccol.getName().replace(srccol.getTable().getName(), destable));
        model.put("ORDERNO", orderno);
        model.put("MODIFIEDDATE", new Timestamp(System.currentTimeMillis()));
        model.put("CREATIONDATE", new Timestamp(System.currentTimeMillis()));
        model.put("AD_TABLE_ID", destabid);
        model.put("DBNAME", srccol.isVirtual() ? (srccol.getName().replace(srccol.getTable().getName(), destable)) : srccol.getName());
        Long hrcol = model.getLong("REF_HRCOLUMN_ID");
        if (hrcol != null) {
            model.put("REF_HRCOLUMN_ID", idMapper.get(hrcol));
        }
        mapperShortcut.insert(model, "ad_column");
    }

    private JSONObject keyToUpper(JSONObject model) {
        JSONObject newModel = new JSONObject();
        for (String key : model.keySet()) {
            newModel.put(key.toUpperCase(), model.get(key));
        }
        return newModel;
    }

    private ValueHolder result(QuerySession session, int code, String message) {
        ValueHolder vh = new ValueHolder();
        vh.put("code", code);
        vh.put("message", Resources.getMessage(message, session.getLocale()));
        return vh;
    }

    @Override
    @Transactional
    public ValueHolder execute(QuerySession session) throws NDSException {

        TableManager manager = session.getTableManager();

        Table table = manager.getTable("AD_Table");
        DefaultWebEvent event = session.getEvent();
        // following check directory permission needs this parameter
        event.setParameter("directory", table.getSecurityDirectory(manager));

        // TODO: 权限控制暂时未实现
        //helper.checkDirectoryWritePermission(event, helper.getOperator(event));
        JSONObject param = (JSONObject) event.getParameterValue("param");
        String srctable = param.getString("srctable").toUpperCase();
        String destable = param.getString("destable").toUpperCase();
        String destdesc = param.getString("destdesc");

        Table srctab = manager.getTable(srctable);
        if (srctab == null) {
            return result(session, -1, "源表不存在或已被删除");
        }

        if (destable == null || (destable = destable.trim()).length() == 0) {
            return result(session, -1, "表名不能为空");
        }

        if (destdesc == null || (destdesc = destdesc.trim()).length() == 0) {
            return result(session, -1, "表描述不能为空");
        }

        if (adTableMapper.exists(destable)) {
            return result(session, -1, "目标表名已存在");
        }

        if (directoryMapper.exists(destable + "_LIST")) {
            return result(session, -1, "目标安全目录已存在");
        }

        User user = session.getUser();
        int formtabid = srctab.getId();

        /*
        helper.executeStoredProcedure("ad_table_clone", params, false);
    	*/
        try {
            long tableid = Tools.getSequence("ad_table");
            long directoryid = Tools.getSequence("directory");


            {   //复制目录
                JSONObject model = directoryMapper.selectFullByTableId(formtabid);
                if (model == null) {
                    model = new JSONObject();
                } else {
                    model = keyToUpper(model);
                }
                model.put("ID", directoryid);
                model.put("NAME", destable + "_LIST");
                model.put("DESCRIPTION", destdesc);
                model.put("URL", "/html/nds/sheet/objects.jsp?table=" + destable);
                model.put("AD_TABLE_ID", tableid);
                model.put("OWNERID", user.getId());
                model.put("MODIFIERID", user.getId());
                model.put("OWNERNAME", user.getName());
                model.put("MODIFIERNAME", user.getName());
                model.put("OWNERENAME", user.getEname());
                model.put("MODIFIERENAME", user.getEname());
                model.put("AD_CLIENT_ID", Integer.valueOf(user.getClientId()).longValue());
                model.put("AD_ORG_ID", Integer.valueOf(user.getOrgId()).longValue());
                model.put("MODIFIEDDATE", new Timestamp(System.currentTimeMillis()));
                model.put("CREATIONDATE", new Timestamp(System.currentTimeMillis()));
                mapperShortcut.insert(model, "DIRECTORY");
            }

            {   // 复制表
                JSONObject model = adTableMapper.selectFullById(formtabid);
                model = keyToUpper(model);
                model.put("ID", tableid);
                if (!model.containsKey("REALTABLE_ID")) {
                    model.put("REALTABLE_ID", formtabid);
                }
                model.put("NAME", destable);
                model.put("DESCRIPTION", destdesc);
                model.put("PK_COLUMN_ID", null);
                model.put("AK_COLUMN_ID", null);
                model.put("U_CLOB_ID", null);
                model.put("DIRECTORY_ID", directoryid);
                model.put("MODIFIEDDATE", new Timestamp(System.currentTimeMillis()));
                model.put("CREATIONDATE", new Timestamp(System.currentTimeMillis()));
                model.put("ROWCNT", 0);

                mapperShortcut.insert(model, "AD_TABLE");
            }

            ArrayList columns = srctab.getAllColumns();
            HashMap<Long, Long> idMapper = new HashMap<>();
            //创建column_id mapper
            for (int i = 0; i < columns.size(); i++) {
                Column srccol = (Column) columns.get(i);
                long oldcolid = srccol.getId();
                long newcolid = Tools.getSequence("ad_column");
                idMapper.put(oldcolid, newcolid);
            }

            for (int i = 0; i < columns.size(); i++) {
                Column srccol = (Column) columns.get(i);
                copycolumn(tableid, destable, srccol, 1, idMapper);
            }

            adTableMapper.syncPkAkDk(tableid);
            long[] refTableids = adRefbyTableMapper.selectIdsByTableId(formtabid);
            for (long srcRefTableId : refTableids) {
                long refTableId = Tools.getSequence("AD_REFBYTABLE");
                adRefbyTableMapper.clone(srcRefTableId, refTableId, tableid, new Timestamp(System.currentTimeMillis()));
            }

            long sqlId = Tools.getSequence("AD_TABLESQL");
            adTableSqlMapper.clone(sqlId, formtabid, tableid, new Timestamp(System.currentTimeMillis()));

            ValueHolder vh = result(session, 0, "OK");
            JSONObject data = new JSONObject();
            data.put("objid", tableid);
            data.put("tablename", "AD_TABLE");
            vh.put("data", data);
            return vh;
        } catch (Throwable t) {
            log.error("clone_table: exception", t);
            if ((t instanceof NDSException))
                throw ((NDSException) t);

            throw new NDSException(t.getMessage(), t);
        }

    }
}
